home *** CD-ROM | disk | FTP | other *** search
/ Dr. Windows 3 / dr win3.zip / dr win3 / WINSOUND / WAVSMALL.ZIP / WAVSMALL.TAR / WAVSMALL / sound / play.c < prev    next >
C/C++ Source or Header  |  1993-07-17  |  9KB  |  343 lines

  1. /**************************************************************************************************/
  2. /* WAV-File player/recorder - Version 0.1                               */
  3. /* using code of recplay.c from Audio Utilities for Linux 2.0 (c) Liam Corner                     */
  4. /* (C) FF-Soft '93                                           */
  5. /* Andre Fuechsel; email: af1@irz.inf.tu-dresden.de / fuechsel@freia.inf.tu-dresden.de            */
  6. /**************************************************************************************************/
  7.  
  8. #include <stdio.h>
  9. #include <getopt.h>
  10. #include <fcntl.h>
  11. #include <linux/soundcard.h>
  12.  
  13. #define RECORD 0
  14. #define PLAY 1
  15. #define AUDIO "/dev/dsp"
  16.  
  17. typedef unsigned long DWORD;
  18. typedef unsigned short WORD;
  19.  
  20. typedef struct {        /* header for WAV-Files */
  21.     char main_chunk[4];    /* 'RIFF' */
  22.     DWORD length;        /* length of file */
  23.     char chunk_type[4];    /* 'WAVE' */
  24.     char sub_chunk[4];    /* 'fmt' */
  25.     DWORD length_chunk;    /* length sub_chunk, always 16 bytes */
  26.     WORD format;        /* always 1 = PCM-Code */
  27.     WORD modus;        /* 1 = Mono, 2 = Stereo */
  28.     DWORD sample_fq;    /* Sample Freq */
  29.     DWORD byte_p_sec;    /* Data per sec */
  30.     WORD byte_p_spl;    /* bytes per sample, 1=8 bit, 2=16 bit (mono)
  31.                              2=8 bit, 4=16 bit (stereo) */
  32.     WORD bit_p_spl;        /* bits per sample, 8, 12, 16 */
  33.     char data_chunk[4];    /* 'data' */
  34.     DWORD data_length;    /* length of data */
  35. } wave_header;
  36.  
  37. int quiet_mode=0;
  38. int time_limit=0;
  39. int stereo = 0;
  40. DWORD speed = 0, sample_size = 0;
  41. int force_speed = 0, force_stereo = 0, force_sample_size = 0;
  42. int mode, omode;
  43.  
  44. void err(char *err_str)            /* future expansion planned */ 
  45. {
  46.     fprintf(stderr, "%s \n", err_str);
  47. }
  48.  
  49. int header_check(wave_header *head) 
  50. {
  51.     unsigned p;
  52.     int severity = 0;
  53.     
  54.     p = head->length - head->data_length;
  55.     if ((p != 36) && (p != 37)) { 
  56.         err("wrong length difference");
  57.         severity = 2;
  58.     }
  59.  
  60.     if (strncmp(head->main_chunk, "RIFF", 4)) {
  61.         err("not in RIFF-Format");
  62.         severity = 2;
  63.     }
  64.  
  65.     if (strncmp(head->chunk_type, "WAVE", 4)) {
  66.         err("not a WAVE-Type");
  67.         severity = 2;
  68.     }
  69.         
  70.     if (strncmp(head->sub_chunk, "fmt ", 4)) {
  71.         err("not a WAVE-Format");
  72.         severity = 2;
  73.     }
  74.  
  75.     if ((head->sample_fq * head->byte_p_spl) != head->byte_p_sec) {
  76.         err("wrong speed/freq."); 
  77.         if (!severity) severity = 1;
  78.     }
  79.  
  80.     if (severity == 2) return(0); else return(1);
  81. }
  82.  
  83. void recplay(char *name)
  84. {
  85.     int l, c, count;
  86.     int fd, fd1, audio;
  87.     int abuf_size;
  88.     DWORD length; 
  89.     wave_header head;
  90.     char *audiobuf;
  91.     char tmp_name[] = "tmp.wav";        /* temporary file */
  92.  
  93.     if (mode == PLAY) {
  94.         if (!name) {
  95.             fd = 0;
  96.             name = "stdin";
  97.         } else {
  98.             if ((fd = open (name, O_RDONLY, 0)) == -1) {
  99.                 perror(name);
  100.                 exit(-1);
  101.             }
  102.         }
  103.         read(fd, &head, sizeof(head));
  104.         if (!header_check(&head)) exit(-1);
  105.  
  106.         if (!force_stereo) stereo = (head.modus == 2);
  107.         length = head.data_length;
  108.         if (!force_speed) speed = head.sample_fq;
  109.         if (!force_sample_size) sample_size = head.bit_p_spl;
  110.     } else {                /* mode = RECORD */
  111.         remove(tmp_name);
  112.         if ((fd = open (tmp_name, O_WRONLY | O_CREAT, 0666)) == -1) {
  113.             perror(tmp_name);
  114.             exit(-1);
  115.         }
  116.         /* create header */
  117.         strncpy(head.main_chunk, "RIFF", 4);
  118.         strncpy(head.chunk_type, "WAVE", 4);
  119.         strncpy(head.sub_chunk, "fmt ", 4);
  120.         strncpy(head.data_chunk, "data", 4);
  121.         head.length = 0;            /* to be calculated later */ 
  122.         head.length_chunk = 16;
  123.         head.format = 1;
  124.         head.modus = stereo ? 2 : 1;        
  125.         head.sample_fq = speed;
  126.  
  127.         if (!stereo)             /* mono */
  128.             if (sample_size == 8)
  129.                 head.byte_p_spl = 1;
  130.             else 
  131.                 head.byte_p_spl = 2;
  132.         else                /* stereo */
  133.             if (sample_size == 8)
  134.                 head.byte_p_spl = 2;
  135.             else
  136.                 head.byte_p_spl = 4;
  137.  
  138.         head.byte_p_sec = speed * head.byte_p_spl;
  139.  
  140.         head.bit_p_spl = sample_size;
  141.         head.data_length = 0;            /* to be calculated later */
  142.     }
  143.  
  144.     if (!time_limit) 
  145.         count = 0x7fffffff;
  146.     else {
  147.         count = time_limit * speed;
  148.         if (stereo) count *= 2;
  149.         if (sample_size != 8) count *=2;
  150.     }
  151.  
  152.     if (!quiet_mode) {
  153.         if (mode == PLAY)
  154.             fprintf(stderr, "Playing: %s", name);
  155.         else
  156.             if (!name) 
  157.                 fprintf(stderr, "Recording: stdout");
  158.             else
  159.                 fprintf(stderr, "Recording: %s", name);
  160.         if (!time_limit) 
  161.             fprintf(stderr, " (full-song)\n");
  162.         else
  163.             fprintf(stderr, " %u secs\n", time_limit);
  164.         if (stereo) 
  165.             fprintf(stderr, "Stereo-Sample");
  166.         else
  167.             fprintf(stderr, "Mono-Sample");
  168.         fprintf(stderr, ", speed: %u Hz, %u Bit per Sample\n", speed, sample_size);
  169.     }
  170.  
  171.     audio = open(AUDIO, omode, 0);
  172.     if (audio == -1) {
  173.         perror(AUDIO);
  174.         exit(-1);
  175.     }
  176.  
  177.     abuf_size = ioctl(audio, SNDCTL_DSP_GETBLKSIZE);
  178.     if (abuf_size < 4096 || abuf_size > 65536) {
  179.         if (abuf_size == -1)
  180.             perror(AUDIO);
  181.         else
  182.             fprintf(stderr, "Invalid audio buffer size %d\n", abuf_size);
  183.         exit(-1);
  184.     }
  185.  
  186.     if ((audiobuf = malloc(abuf_size)) == NULL) {
  187.         fprintf(stderr, "Unable to allocate output buffer\n");
  188.         exit(-1);
  189.     }
  190.  
  191.     if (ioctl(audio, SNDCTL_DSP_SAMPLESIZE, sample_size) != sample_size) {
  192.         fprintf(stderr, "Unable to set sample size\n");
  193.         exit(-1);
  194.     }
  195.  
  196.     stereo = ioctl(audio, SNDCTL_DSP_STEREO, stereo);
  197.  
  198.     if ((speed = ioctl(audio, SNDCTL_DSP_SPEED, speed)) == -1) {
  199.         fprintf(stderr, "Unable to set audio speed\n");
  200.         perror(AUDIO);
  201.         exit(-1);
  202.     }
  203.  
  204.     if (mode == PLAY) {
  205.         while(count) {
  206.             c = count;
  207.             if (c > abuf_size) c = abuf_size;
  208.  
  209.             if ((l=read(fd, audiobuf, c)) > 0) {
  210.                 if (write(audio, audiobuf, l) != l) {
  211.                     perror(AUDIO);
  212.                     exit(-1);
  213.                 }
  214.                 count -= l;
  215.             } else {
  216.                 if (l == -1) {
  217.                     perror(name);
  218.                     exit(-1); 
  219.                 }
  220.                 count = 0;    /* stop */
  221.             }
  222.         }
  223.  
  224.         if (fd) close(fd);
  225.         close(audio);
  226.     } else {            /* mode = RECORD */
  227.         if (!quiet_mode) fprintf(stderr, "...recording\n");
  228.         while(count) {
  229.             c = count;
  230.             if (c > abuf_size) c = abuf_size;
  231.  
  232.             if ((l=read(audio, audiobuf, c)) > 0) {
  233.                 if (write(fd, audiobuf, l) != l) {
  234.                     perror(tmp_name);
  235.                     exit(-1);
  236.                 }
  237.                 count -= l;
  238.                 head.data_length += l;
  239.             } else {
  240.                 if (l == -1) {
  241.                     perror (AUDIO);
  242.                     exit(-1);
  243.                 }
  244.             }
  245.         }
  246.         /* now lets correct the header */
  247.  
  248.         close(fd);
  249.         close(AUDIO);
  250.  
  251.         head.length = head.data_length + 36;
  252.  
  253.         /* copy the temporary file to the output file with corrected header */
  254.  
  255.         if (!name) {
  256.             fd = 1;
  257.             name = "stdout";
  258.         } else {
  259.             remove(name);
  260.             if ((fd = open(name, O_WRONLY | O_CREAT, 0666)) == -1) {
  261.                 perror(name);
  262.                 exit(-1);
  263.             }
  264.         }
  265.         if ((fd1 = open(tmp_name, O_RDONLY, 0)) == -1) {
  266.             perror(tmp_name);
  267.             exit(-1);
  268.         }
  269.  
  270.         if (write(fd, &head, sizeof(head)) != sizeof(head)) {
  271.             perror(name);
  272.             exit(-1);
  273.         }
  274.         if (!quiet_mode) fprintf(stderr, "...copying\n");
  275.         while (l = read(fd1, audiobuf, abuf_size)) {
  276.             if (write(fd, audiobuf, l) != l) {
  277.                 perror(name);
  278.                 exit(-1);
  279.             }
  280.         }
  281.         close(fd);
  282.         close(fd1);
  283.         remove(tmp_name);
  284.         if (!quiet_mode) fprintf(stderr, "READY\n");
  285.     }
  286. }
  287.  
  288. main(int argc, char *argv[])
  289. {
  290.     char c;
  291.  
  292.     if (strstr(argv[0], "play")) {
  293.         mode = PLAY;
  294.         omode = O_WRONLY;
  295.     } else if (strstr(argv[0], "record")) {
  296.         mode = RECORD;
  297.         omode = O_RDONLY;
  298.     } else {
  299.         fprintf(stderr, "%s: command should either be named play or record\n", argv[0]);
  300.         exit(-1);
  301.     }
  302.  
  303.     while((c = getopt(argc, argv, "qs:St:b:h")) != EOF)
  304.         switch (c) {
  305.             case 'q': quiet_mode=1; break;
  306.             case 's': speed = atoi(optarg); force_speed = 1; break;
  307.             case 'S': stereo = force_stereo = 1; break;
  308.             case 't': time_limit = atoi(optarg); break;
  309.             case 'b': sample_size = atoi(optarg); force_sample_size = 1; break;
  310.             case 'h': 
  311.                fprintf(stderr, 
  312.     "Usage: %s [-h] [-q] [-s speed] [-S] [-t limit] [-b bits] filename...\n\n", argv[0]);
  313.                fprintf(stderr, "Switches:\n  -h .. displays this help text\n");
  314.                fprintf(stderr, "  -q .. quiet mode; don't display");
  315.                fprintf(stderr, " any information about the sample\n");
  316.                fprintf(stderr, "  -s .. force speed\n  -S .. force stereo\n");
  317.                fprintf(stderr, "  -t .. time limit\n");
  318.                fprintf(stderr, "  -b .. force bit_p_spl (8, 12, 16)\n\n");
  319.                fprintf(stderr, "Normally speed, stereo/mono and bit_p_spl");
  320.                fprintf(stderr, " will be read from the given file. Using the\n");
  321.                fprintf(stderr, "switches shown above you can set your own.\n");
  322.                exit(-1);
  323.             default: fprintf(stderr, 
  324.     "Usage: %s [-h] [-q] [-s speed] [-S] [-t limit] [-b bits] filename...\n\n", argv[0]);
  325.                  exit(-1);
  326.         }
  327.  
  328.     if (mo